/*
 * All rights Reserved, Copyright (C) WANGJIAN LIMITED 2019
 * FileName: IndexView.java
 * Version:  $Revision$
 * Modify record:
 * NO. |     Date       |    Name         |      Content
 * 1   | 2019年1月29日        | JFTT)wangjian    | original version
 */
package com.pl.config;

import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.pl.config.security.oauth2.Oauth2HttpMessageConverter;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.ArrayList;
import java.util.List;

/**
 * class name:IndexView <BR>
 * class description: please write your description <BR>
 * Remark: <BR>
 * @version 1.00 2019年1月29日
 * @author JFTT)wangjian
 */
@Configuration
public class Config implements WebMvcConfigurer{
	
	private static Logger log = LogManager.getLogger();
    
    //上传地址的物理路径
  	@Value("${UPLOAD_PATH}")
    private String realPathPrev;
  	
  	//上传地址的虚拟路径
    @Value("${UPLOAD_VIRTUAL_PATH}")
    private String virtualPath;
	
    /**
     * 首页设置
     */
	@Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("login/login");
    }
	
	/**
	  *    统一返回类型设置
     */
	@Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer.defaultContentType(MediaType.APPLICATION_JSON);
    }
	
	/**
	 * 虚拟路径设置
	 */
	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		log.info("虚拟路径配置  " + virtualPath + "  " + realPathPrev);
		registry.addResourceHandler(virtualPath + "/**").addResourceLocations("file:" + realPathPrev + "/");
	}
	
	/**
     * 重写添加拦截器方法并添加配置拦截器
     */
//    @Override
//    public void addInterceptors(InterceptorRegistry registry) {
//    	/**
//    	 * 使用拦截器拦截请求，但是不拦截静态资源
//    	 */
//        registry.addInterceptor(systemInterceptor)
//         			.addPathPatterns("/**")
//         			.excludePathPatterns("/js/**", "/css/**", "/images/**", "/error", virtualPath + "/**");
//    }
    
    /**
     * 修改自定义消息转换器
     * @param converters 消息转换器列表
     * fastJSON
     */
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {

        /**
         先把JackSon的消息转换器删除.
         备注: (1)源码分析可知，返回json的过程为:
                Controller调用结束后返回一个数据对象，for循环遍历conventers，找到支持application/json的HttpMessageConverter，然后将返回的数据序列化成json。
               具体参考org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor的writeWithMessageConverters方法
               (2)由于是list结构，我们添加的fastjson在最后。因此必须要将jackson的转换器删除，不然会先匹配上jackson，导致没使用fastjson
        */
        for (int i = converters.size() - 1; i >= 0; i--) {
            if (converters.get(i) instanceof MappingJackson2HttpMessageConverter) {
                converters.remove(i);
            }
        }

        //创建配置类
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        //修改配置返回内容的过滤
        fastJsonConfig.setSerializerFeatures(
                SerializerFeature.WriteMapNullValue,
                SerializerFeature.WriteNullListAsEmpty   //List字段如果为null，输出为[]，而非null。
        );

        //创建fastJson消息转换器
        FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
        List<MediaType> supportedMediaTypes = new ArrayList<>();
        supportedMediaTypes.add(MediaType.APPLICATION_JSON);
        supportedMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
        supportedMediaTypes.add(MediaType.APPLICATION_ATOM_XML);
        supportedMediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED);
        supportedMediaTypes.add(MediaType.APPLICATION_OCTET_STREAM);
        supportedMediaTypes.add(MediaType.APPLICATION_PDF);
        supportedMediaTypes.add(MediaType.APPLICATION_RSS_XML);
        supportedMediaTypes.add(MediaType.APPLICATION_XHTML_XML);
        supportedMediaTypes.add(MediaType.APPLICATION_XML);
        supportedMediaTypes.add(MediaType.IMAGE_GIF);
        supportedMediaTypes.add(MediaType.IMAGE_JPEG);
        supportedMediaTypes.add(MediaType.IMAGE_PNG);
        supportedMediaTypes.add(MediaType.TEXT_EVENT_STREAM);
        supportedMediaTypes.add(MediaType.TEXT_HTML);
        supportedMediaTypes.add(MediaType.TEXT_MARKDOWN);
        supportedMediaTypes.add(MediaType.TEXT_PLAIN);
        supportedMediaTypes.add(MediaType.TEXT_XML);
        fastConverter.setSupportedMediaTypes(supportedMediaTypes);
        
        fastConverter.setFastJsonConfig(fastJsonConfig);

        // 添加支持的MediaTypes;不添加时默认为*/*,也就是默认支持全部
        // 但是MappingJackson2HttpMessageConverter里面支持的MediaTypes为application/json
        // 参考它的做法, fastjson也只添加application/json的MediaType
        //List<MediaType> fastMediaTypes = new ArrayList<>();
        //fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
        //fastConverter.setSupportedMediaTypes(fastMediaTypes);
        
        //将fastjson添加到视图消息转换器列表内
        converters.add(fastConverter);
        
        converters.add(0, new Oauth2HttpMessageConverter());
    }
}
